home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-win32 / sound.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  6KB  |  241 lines

  1. /* 
  2.  * UAE - The Un*x Amiga Emulator
  3.  *
  4.  * Win32 interface
  5.  *
  6.  * Copyright 1997 Mathias Ortmann
  7.  */
  8.  
  9. #ifdef __GNUC__
  10. #define __int64 long long
  11. #include "machdep/winstuff.h"
  12. #else
  13. #include <windows.h>
  14. #include <ddraw.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <commctrl.h>
  18. #include <commdlg.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <sys/stat.h>
  22. #include <io.h>
  23. #endif
  24.  
  25. #include "config.h"
  26. #include "sysconfig.h"
  27. #include "sysdeps.h"
  28. #include "options.h"
  29. #include "gensound.h"
  30. #include "sounddep/sound.h"
  31. #include "events.h"
  32. #include "uae.h"
  33. #include "include/memory.h"
  34. #include "custom.h"
  35. #include "osdep/win32gui.h"
  36. #include "resource.h"
  37. #include "osdep/win32.h"
  38.  
  39. /* Sound emulation, Win32 interface */
  40. HGLOBAL hWaveHdr;
  41. LPWAVEHDR lpWaveHdr;
  42. HANDLE hData;
  43. LPSTR lpData;
  44. HANDLE hWaveOut;
  45.  
  46. static WAVEFORMATEX wavfmt;
  47. char *sndptr, *sndptrmax, soundneutral;
  48. signed int bytesinbuf;
  49. static HGLOBAL hSndbuf;
  50. MMTIME mmtime;
  51. static DWORD basevsynctime;
  52.  
  53. int stereo_sound;
  54.  
  55. signed long bufsamples;
  56. int samplecount;
  57. DWORD soundbufsize;
  58.  
  59. void close_sound (void)
  60. {
  61.     if (hWaveOut) {
  62.     waveOutReset (hWaveOut);
  63.     waveOutUnprepareHeader (hWaveOut, lpWaveHdr, sizeof (WAVEHDR));
  64.  
  65.     GlobalUnlock (hWaveHdr);
  66.     GlobalFree (lpWaveHdr);
  67.  
  68.     GlobalUnlock (hData);
  69.     GlobalFree (hData);
  70.  
  71.     waveOutClose (hWaveOut);
  72.  
  73.     hWaveOut = NULL;
  74.     }
  75. }
  76.  
  77. void startsound (void)
  78. {
  79.     lpWaveHdr->lpData = lpData;
  80.     lpWaveHdr->dwBufferLength = soundbufsize;
  81.     lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
  82.     lpWaveHdr->dwLoops = 0x7fffffffL;
  83.     waveOutPrepareHeader (hWaveOut, lpWaveHdr, sizeof (WAVEHDR));
  84.  
  85.     if (waveOutWrite (hWaveOut, lpWaveHdr, sizeof (WAVEHDR))) {
  86.     MyOutputDebugString ("Failed to write to sound card\n");
  87.     return;
  88.     }
  89. }
  90.  
  91. void stopsound (void)
  92. {
  93.     sndptr = lpData;
  94.     samplecount = 0;
  95.     memset (lpData, soundneutral, soundbufsize);
  96.     waveOutReset (hWaveOut);
  97. }
  98.  
  99. static int init_sound_win32 (void)
  100. {
  101.     MMRESULT mmres;
  102.     DWORD id;
  103.     long i;
  104.     __int64 freq;
  105.  
  106.     if (currprefs.produce_sound < 0) {
  107.     currprefs.produce_sound = 0;
  108.     MyOutputDebugString ("FrameSync disabled.\n");
  109.     } else {
  110. #ifdef FRAME_RATE_HACK
  111.     if (!vsynctime) {
  112.         DWORD oldpri = GetPriorityClass (GetCurrentProcess ());
  113.  
  114.         MyOutputDebugString ("Measuring clock rate...\n");
  115.  
  116.         SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS);
  117.         i = read_processor_time ();
  118.         Sleep (1000);
  119.         i = read_processor_time () - i;
  120.         SetPriorityClass (GetCurrentProcess (), oldpri);
  121.  
  122.         MyOutputDebugString ("Your machine is running at approx. %d Hz\n", i);
  123.         vsynctime = i / 50;
  124.     } else if (vsynctime > 0)
  125.         vsynctime *= 1000 / 50;
  126.     else {
  127.         MyOutputDebugString ("Using QueryPerformanceCounter()...\n");
  128.         QueryPerformanceFrequency (&freq);
  129.         vsynctime = freq / 50;
  130.         useqpc = 1;
  131.     }
  132.  
  133.     if (!vsynctime)
  134.         MyOutputDebugString ("No performance counters available. Bad.\n");
  135.     else
  136.         MyOutputDebugString ("FrameSync enabled. Ticks per frame: %d\n", vsynctime);
  137. #else
  138.     vsynctime = 0;
  139. #endif
  140.     }
  141.  
  142.     if (currprefs.produce_sound < 2) {
  143.     MyOutputDebugString ("Sound output disabled.\n");
  144.     return 1;
  145.     }
  146.     mmtime.wType = TIME_SAMPLES;
  147.  
  148.     wavfmt.wFormatTag = WAVE_FORMAT_PCM;
  149.     wavfmt.nChannels = 1 + stereo_sound;
  150.     wavfmt.nSamplesPerSec = currprefs.sound_freq;
  151.     wavfmt.nBlockAlign = currprefs.sound_bits / 8 * wavfmt.nChannels;
  152.     wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * currprefs.sound_freq;
  153.     wavfmt.wBitsPerSample = currprefs.sound_bits;
  154.  
  155.     soundneutral = currprefs.sound_bits == 8 ? 128 : 0;
  156.     bufsamples = 4096 * currprefs.sound_freq / 22050;
  157.     soundbufsize = bufsamples * wavfmt.nBlockAlign;
  158.  
  159.     if (!(hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, soundbufsize))) {
  160.     MyOutputDebugString ("Failed to allocate sound buffer!\n");
  161.     return 0;
  162.     }
  163.     if (!(lpData = GlobalLock (hData))) {
  164.     MyOutputDebugString ("Failed to lock sound buffer!\n");
  165.     return 0;
  166.     }
  167.     if (!(hWaveHdr = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof (WAVEHDR)))) {
  168.     MyOutputDebugString ("Failed to allocate wave header!\n");
  169.     return 0;
  170.     }
  171.     if (!(lpWaveHdr = (LPWAVEHDR) GlobalLock (hWaveHdr))) {
  172.     MyOutputDebugString ("Failed to lock wave header!\n");
  173.     return 0;
  174.     }
  175.     if (mmres = waveOutOpen (&hWaveOut, WAVE_MAPPER, &wavfmt, 0, 0, CALLBACK_NULL)) {
  176.     MyOutputDebugString ("Sound device failed to open with error code %d.\n", mmres);
  177.     return 0;
  178.     }
  179.     basevsynctime = vsynctime;
  180.     sndptrmax = lpData + soundbufsize;
  181.  
  182.     stopsound ();
  183.     startsound ();
  184.  
  185.     return currprefs.sound_freq;
  186. }
  187.  
  188. void adjust_sound_timing (void)
  189. {
  190.     static DWORD last;
  191.     signed long diff;
  192.  
  193.     waveOutGetPosition (hWaveOut, &mmtime, sizeof (mmtime));
  194.     if (!mmtime.u.sample)
  195.     mmtime.u.sample++;
  196.  
  197.     if (last == mmtime.u.sample)
  198.     return;
  199.     last = mmtime.u.sample;
  200.  
  201.     diff = samplecount - mmtime.u.sample;
  202.  
  203.     if (diff < -bufsamples || diff > bufsamples) {
  204.     samplecount = mmtime.u.sample;
  205.     sndptr = lpData + (samplecount % bufsamples) * wavfmt.nBlockAlign;
  206.     }
  207.     if (diff < 0)
  208.     vsynctime = basevsynctime * 5 / 6;
  209.     else if (diff > 0)
  210.     vsynctime = basevsynctime * 7 / 6;
  211. }
  212.  
  213. int setup_sound (void)
  214. {
  215.     sound_available = 1;
  216.     return 1;
  217. }
  218.  
  219. int init_sound (void)
  220. {
  221.     int rate;
  222.  
  223.     if ((rate = init_sound_win32 ()) < 2)
  224.     return rate;
  225.  
  226.     sample_evtime = (long) maxhpos *maxvpos * 50 / rate;
  227.  
  228.     if (currprefs.sound_bits == 16) {
  229.     init_sound_table16 ();
  230.     eventtab[ev_sample].handler = sample16_handler;
  231.     } else {
  232.     init_sound_table8 ();
  233.     eventtab[ev_sample].handler = sample8_handler;
  234.     }
  235.  
  236.     MyOutputDebugString ("Sound driver found and configured for %d bits at %d Hz %s\n",
  237.              currprefs.sound_bits, rate, stereo_sound ? "stereo" : "");
  238.  
  239.     return 1;
  240. }
  241.